package de.luh.slimpp.generator

import de.luh.slimpp.slimPP.Method

/**
* This enhances the Slim++ Method with some information necessary for code generation (e.g. the
* containing class and some properties like override etc.).
*/
class EnhancedMethod {
	public val Method original
	EnhancedClass containingClass
	public boolean overrides

	new(EnhancedClass cls, Method original, boolean overrides) {
		this.original = original
		this.containingClass = cls
		this.overrides = overrides
	}

	/**
	* Returns true if the method has to have a definition in the code. This is not the case for pure
	* virtual methods for example.
	*/
	def mustBeDefined() {
		!pureVirtual
	}

	/**
	* Returns true if the definition of this method has to be placed inside the class' header file. This
	* is necessary if there are template parameters involved.
	*/
	def mustBeDefinedInHeader() {
		val classHasTemplates = containingClass.original.template != null &&
			!containingClass.original.template.parameters.empty
		val methodHasTemplates = original.template != null && !original.template.parameters.empty
		return mustBeDefined && (classHasTemplates || methodHasTemplates)
	}

	def isPureVirtual() {
		!overrides && (containingClass.original.type.interface || original.virtual)
	}

	def isVirtual() {
		pureVirtual || containingClass.original.type.abstract
	}

	override boolean equals(Object other) {
		switch other {
			EnhancedMethod:
				if (this.original.name != other.original.name) {
					return false
				} else if (this.original.parameters.size != other.original.parameters.size) {
					return false
				} else {
					if (this.original.parameters.size > 0) {
						for (i : 0 .. this.original.parameters.size - 1) {
							if (this.original.parameters.get(i).type != other.original.parameters.get(i).type) {
								return false
							}
						}
					}
					return true
				}
			default:
				return false
		}
	}

	override int hashCode() {
		original.name.hashCode
	}
}
